package com.glodon.paas.job.agent.cli;

import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class GnuCli implements Cli {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    static {
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
    private Set<String> paramNames = new HashSet<String>();

    @Override
    public String generate(Map map) {
        Map<String, String> result = new LinkedHashMap<String, String>();
        write(map, result, "");
        StringBuilder cli = new StringBuilder();
        Set<Entry<String, String>> results = result.entrySet();
        for (Entry<String, String> entry : results) {
            cli.append("--").append(entry.getKey()).append(" \"").append(entry.getValue()).append("\" ");
        }
        if (cli.length() > 0)
            cli.deleteCharAt(cli.length() - 1); // remove last space
        return cli.toString();
    }

    private void write(Map<String, Object> model, Map<String, String> result, String path) {
        Set<Entry<String, Object>> entries = model.entrySet();
        for (Entry<String, Object> entry : entries) {
            String key = entry.getKey();
            if ("".equals(path) && !paramNames.contains(key))
                continue;
            Object value = entry.getValue();
            if (value instanceof Map) {
                Map member = (Map) value;
                write(member, result, entry.getKey());
            } else if (value instanceof List) {
                List values = (List) value;
                StringBuffer s = new StringBuffer();
                for (Object v : values) {
                    s.append(v).append(",");
                }
                if (s.length() > 0)
                    s.deleteCharAt(s.length() - 1); // remove last ,
                result.put(path + (path.equals("") ? "" : "-") + key, s.toString());
            } else {
                result.put(path + (path.equals("") ? "" : "-") + key, value == null ? "null" : value.toString());
            }
        }
    }

    public void addParamNames(String... names) {
        for (String name : names)
            paramNames.add(name);
    }
}
